package com.unittec.drainage.provider.utils;

/**
 * @Description:
 * @author: chendaren
 * @CreateDate: 2020/12/16 16:59
 */
public class CronUtil {
    /**
     * 执行方式
     *
     */
    public enum ExecuteType {
        /**
         *
         */
        EveryDay,
        /**
         *
         */
        EveryWeek,
        /**
         *
         */
        EveryMonth;
    }

    public static class DayCron extends BaseCron {

        public DayCron(Integer hour, Integer minute, Integer second) {
            super(ExecuteType.EveryDay, hour, minute, second);
        }

        public static String cron(Integer hour, Integer minute, Integer second) {
            return new DayCron(hour, minute, second).toString();
        }

    }

    public static class WeekCron extends BaseCron {

        public WeekCron(Integer hour, Integer minute, Integer second) {
            super(ExecuteType.EveryWeek, hour, minute, second);
        }

        /**
         * 一周的哪几天
         */
        public String day(Integer... dayOfWeeks) {
            this.dayOfWeeks = dayOfWeeks;
            return toString();
        }

        public static WeekCron cron() {
            return cron(0, 0, 0);
        }

        public static WeekCron cron(Integer hour, Integer minute, Integer second) {
            return new WeekCron(hour, minute, second);
        }
    }

    public static class MonthCron extends BaseCron {

        public MonthCron(Integer hour, Integer minute, Integer second) {
            super(ExecuteType.EveryMonth, hour, minute, second);
        }

        /**
         * 一个月的哪几天
         */
        public String day(Integer... dayOfMonths) {
            this.dayOfMonths = dayOfMonths;
            return toString();
        }

        public static MonthCron cron() {
            return cron(0, 0, 0);
        }

        public static MonthCron cron(Integer hour, Integer minute, Integer second) {
            return new MonthCron(hour, minute, second);
        }

    }

    /**
     * 表达式
     */
    public static class BaseCron {

        /**
         * 表达式
         */
        private StringBuffer cronExp;

        /***
         * 描述
         */
        private StringBuffer description;

        /**
         * 执行间隔
         */
        ExecuteType executeType;

        /**
         * 一周的哪几天
         */
        Integer[] dayOfWeeks;

        /**
         * 一个月的哪几天
         */
        Integer[] dayOfMonths;

        /** 秒 */
        Integer second = 0;

        /** 分 */
        Integer minute = 0;

        /** 时 */
        Integer hour = 0;

        /**
         * 执行间隔
         *
         * @param executeType
         */
        private BaseCron(ExecuteType executeType, Integer hour, Integer minute, Integer second) {
            this.executeType = executeType;
            this.second = second;
            this.minute = minute;
            this.hour = hour;
        }

        /**
         *
         * 构建Cron表达式
         *
         * @return String
         */
        private String cronExp() {
            cronExp = new StringBuffer("");
            cronExp.append(second).append(" ");// 秒
            cronExp.append(minute).append(" "); // 分
            cronExp.append(hour).append(" "); // 小时
            if (executeType == ExecuteType.EveryDay) {
                cronExp.append("* ");// 日
                cronExp.append("* ");// 月
                cronExp.append("?");// 周
            } else if (executeType == ExecuteType.EveryWeek) {
                cronExp.append("? ");// 一个月中第几天
                cronExp.append("* ");// 月份
                // 周
                for (int i = 0; i < dayOfWeeks.length; i++) {
                    if (i == 0) {
                        cronExp.append(dayOfWeeks[i]);
                    } else {
                        cronExp.append(",").append(dayOfWeeks[i]);
                    }
                }
            } else if (executeType == ExecuteType.EveryMonth) {
                for (int i = 0; i < dayOfMonths.length; i++) {
                    if (i == 0) {
                        cronExp.append(dayOfMonths[i]);
                    } else {
                        cronExp.append(",").append(dayOfMonths[i]);
                    }
                }
                cronExp.append(" * ");// 月份
                // cronExp.append("?");// 周
                if (dayOfWeeks == null) {
                    cronExp.append("?");// 周
                } else {
                    // 周
                    for (int i = 0; i < dayOfWeeks.length; i++) {
                        if (i == 0) {
                            cronExp.append(dayOfWeeks[i]);
                        } else {
                            cronExp.append(",").append(dayOfWeeks[i]);
                        }
                    }
                }

            }
            return cronExp.toString();
        }

        /**
         * 表达式描述
         *
         * @return
         */
        private String description() {
            description = new StringBuffer("");
            if (executeType == ExecuteType.EveryDay) {
                description.append("每天");
                description.append(hour).append("时");
                description.append(minute).append("分");
                description.append(second).append("秒");
                description.append("执行");
            } else if (executeType == ExecuteType.EveryWeek) {
                if (dayOfWeeks != null && dayOfWeeks.length > 0) {
                    StringBuilder days = new StringBuilder();
                    for (int i : dayOfWeeks) {
                        // 把 1,2,3,4,5,6,7 转换成 2,3,4,5,6,7,1
                        int i1;
                        if (i == 7) {
                            i1 = 1;
                        } else if (i == 1) {
                            i1 = 7;
                        } else {
                            i1 = i - 1;
                        }
                        days.append("周").append(i1);
                    }
                    description.append("每周的").append(days);
                }
                description.append(" ");
                description.append(hour).append("时");
                description.append(minute).append("分");
                description.append(second).append("秒");
                description.append("执行");
            } else if (executeType == ExecuteType.EveryMonth) {
                if (dayOfMonths != null && dayOfMonths.length > 0) {
                    StringBuilder days = new StringBuilder();
                    for (int i : dayOfMonths) {
                        days.append(i).append("号");
                    }
                    description.append("每月的").append(days).append(" ");
                }
                description.append(hour).append("时");
                description.append(minute).append("分");
                description.append(second).append("秒");
                description.append("执行");
                // 周
                if (dayOfWeeks != null && dayOfWeeks.length > 0) {
                    description.append("   且只在");
                    StringBuilder days = new StringBuilder();
                    for (int i : dayOfWeeks) {
                        int i1;
                        if (i == 7) {
                            i1 = 1;
                        } else if (i == 1) {
                            i1 = 7;
                        } else {
                            i1 = i - 1;
                        }
                        days.append("周").append(i1);
                    }
                    description.append("每周的").append(days);

                    description.append("执行");
                }
            }
            return description.toString();
        }

        public String build() throws Exception {
            if (cronExp == null || cronExp.length() == 0) {
                if (hour < 0 || hour > 23) {
                    throw new Exception("小时值必须在0~23之间");
                }
                if (minute < 0 || minute > 59) {
                    throw new Exception("分钟值必须在0~59之间");
                }
                if (second < 0 || second > 59) {
                    throw new Exception("秒值必须在0~59之间");
                }
                System.out.println(cronExp());// 生成表达式
                System.out.println(description()); // 生成描述
            }
            return cronExp.toString();
        }

        @Override
        public String toString() {
            try {
                return build();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    public static void main(String[] args) {
        String cron = DayCron.cron(1, 0, 30);
        String day = WeekCron.cron(1, 0, 30).day(2, 3, 4, 5, 6, 7, 1);
        String day1 = MonthCron.cron(1, 0, 30).day(1, 2, 3);

    }
}
